package com.smarttiger.zero.admin.service;

import com.smarttiger.zero.admin.dao.*;
import com.smarttiger.zero.admin.entity.*;
import com.smarttiger.zero.admin.dao.*;
import com.smarttiger.zero.admin.entity.DictionaryModel;
import com.smarttiger.zero.admin.entity.MenuModel;
import com.smarttiger.zero.admin.entity.UsersGroupModel;
import com.smarttiger.zero.admin.entity.UsersModel;
import com.smarttiger.zero.admin.util.Constant;
import com.smarttiger.zero.admin.util.Message;
import com.smarttiger.zero.admin.util.ParamNames;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UsersService extends BaseService<UsersModel>{
    @Autowired
    UsersDao usersDao;

    @Autowired
    MenuDao menuDao;

    @Autowired
    DictionaryDao dictionaryDao;

    @Autowired
    RoleMenuDao roleMenuDao;

    @Autowired
    UsersGroupDao usersGroupDao;

    @PostConstruct
    public void initMethod(){
        super.setDao(usersDao);
    }

    @ParamNames("token")
    public UsersModel findByToken(String token){
        return usersDao.findByToken(token);
    }

    @ParamNames("userName,password")
    public Map<String , Object> login(String userName, String password){
        UsersModel user = usersDao.findByUserNameAndPassword(userName, password);
        String uuid = UUID.randomUUID().toString();
        user.setPassword("");
        List<UsersGroupModel> groups = usersDao.findGroupByUserId(user.getId());
        List<String> groupList = groups.stream().map(e -> e.getId()).collect(Collectors.toList());
        Set<String> menusIds = roleMenuDao.getAllByMutiGroup(groupList);
        List<MenuModel> allMenus= menuDao.getMenuModelsByParentIdIsNull();
        filterMenus(allMenus.get(0),menusIds);
        List<DictionaryModel> dictionaryModels = dictionaryDao.findAll();
        Map<String, DictionaryModel> collect = dictionaryModels.stream().collect(Collectors.toMap(e -> e.getCode(), e -> e));
        Map<String,Object> result = new HashMap<>();
        result.put("user",user);
        result.put("menus", allMenus);
        result.put("dictionarys", collect);

        return result;
    }

    public void filterMenus(MenuModel allMenus,Set<String> menusIds){
        List<MenuModel> collect = allMenus.getMenuModelList().stream()
                .filter(e -> menusIds.contains(e.getId()))
                .collect(Collectors.toList());
        allMenus.setMenuModelList(collect);
        collect.forEach(e ->{
            filterMenus(e,menusIds);
        });
    }


    @Override
    public void save(UsersModel u) {
        List<UsersModel> allByUserNameExists = usersDao.findAllByUserName(u.getUserName());
        if(allByUserNameExists.size()==0){
            super.save(u);
            UsersGroupModel jkz = usersGroupDao.findUsersGroupModelByCode("JKZ");
            if(jkz !=  null){
                List<UsersModel> usersModelList = jkz.getUsersModelList();
                usersModelList.add(u);
                usersGroupDao.save(jkz);
            }
        }
    }

    @ParamNames("name,page")
    public Message getUsers(String name,String page){
        Message message = new Message();
        Pageable pageable = PageRequest.of(Integer.valueOf(page).intValue(), Constant.PAGESIZE, Sort.by(Sort.Direction.DESC,"createDate"));
        Page<UsersModel> all = usersDao.findAll(new Specification<UsersModel>() {
            @Nullable
            @Override
            public Predicate toPredicate(Root<UsersModel> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if(!StringUtils.isEmpty(name)){
                    predicates.add(criteriaBuilder.like(root.get("name"), name+"%"));
                }
                criteriaQuery.orderBy(criteriaBuilder.desc(root.get("createDate")));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        }, pageable);
        long totalElements = all.getTotalElements();
        message.setData(all.getContent());
        message.setTotal((int)totalElements);
        return message;
    }

    @Override
    public List<UsersModel> findAll() {
        Sort sort = new Sort(Sort.Direction.DESC,"createDate");
        return usersDao.findAll(sort);
    }


}
